原本不打算特別寫一篇來講解依賴套件的部分,但在實際操作中踩到了一些問題,經過深入研究後,覺得還是值得分享這段經驗。
這個問題源自於第二篇提到的內容。我最初計畫使用 Poetry 來管理套件,以固定各個 Python 套件的版本,作為解決方案。一開始,我把 Dockerfile 裡面所有 python3-
開頭相關的套件移動到 Poetry 的 pyproject.toml
中,剩下的套件則用 apt
安裝。
基本上這樣的配置運行起來沒有問題,但出現了一個奇怪的情況:在啟動 odoo 時,我一直會看到一個警告訊息:
vobject DeprecationWarning: invalid escape sequence
然而,在使用 Source Install 在我的 WSL(Windows Subsystem for Linux)和官方的 odoo Docker 中,都沒有看到這個警告。
我搜尋後發現這個警告已經被修復了(參考連結),雖然在 vobject 現在最新的釋出版本中還沒合併,但目前對功能也沒有影響。
後續我仔細去比對我的環境和官方的差別,發現我們使用的 Python 版本和 vobject 版本都是一樣的,但只有我的環境會出現這個警告,雖然沒有功能上的影響,但這代表我的 odoo 環境跟官方版本有不同的行為。我認為這在後續的開發中會造成很大的麻煩,而這很可能是因為安裝方式的不同所導致的,這是我非常不希望看到的,可能會花上非常多時間處理莫名的問題,因此前期砸了很多時間來研究解決這個問題。
我前幾天發的文章 分析 Odoo 官方安裝方法:從原始碼、套件管理或 Docker 安裝 中,提到各種安裝方法使用的不同依賴套件,主要分為原始碼安裝和套件安裝。
在原始碼安裝的 debinstall.sh
部分,仔細查看會發現有一個 -l
參數:
if [ "$1" = "-l" -o "$1" = "--list" ]; then
cmd="echo"
大意上就是把原本會用 apt install
執行的部分替換成 echo
,我們可以由此觀察到它會安裝哪些套件。執行後,確實拿到了它從 debian/control
中提取出的列表:
adduser, fonts-dejavu-core, fonts-freefont-ttf, fonts-freefont-otf, fonts-noto-core, fonts-font-awesome, fonts-inconsolata, fonts-roboto-unhinted, gsfonts, libjs-underscore, lsb-base, postgresql-client, python3-babel, python3-chardet, python3-dateutil, python3-decorator, python3-docutils, python3-freezegun, python3-geoip2, python3-jinja2, python3-libsass, python3-lxml-html-clean, python3-lxml, python3-num2words, python3-ofxparse, python3-openssl, python3-passlib, python3-pil, python3-polib, python3-psutil, python3-psycopg2, python3-pydot, python3-pypdf2, python3-qrcode, python3-renderpm, python3-reportlab, python3-requests, python3-rjsmin, python3-stdnum, python3-tz, python3-vobject, python3-werkzeug, python3-xlrd, python3-xlsxwriter, python3-zeep.
原始碼安裝的依賴套件安裝分析基本上就到這裡告一段落。為了更保險,我又去研究了用套件安裝 odoo 時會安裝哪些東西,所以從 odoo 的 nightly server 下載了 odoo_17.0.latest_all.deb
來做分析:
dpkg --info odoo_17.0.latest_all.deb
...
Pre-Depends: init-system-helpers (>= 1.54~)
Depends: python3-babel, python3-chardet, python3-cryptography, python3-dateutil, python3-decorator, python3-docutils, python3-geoip2, python3-gevent, python3-greenlet, python3-idna, python3-jinja2, python3-libsass, python3-lxml, python3-markupsafe, python3-num2words, python3-ofxparse, python3-openssl, python3-passlib, python3-pil, python3-polib, python3-psutil, python3-psycopg2, python3-pydot, python3-pypdf2, python3-qrcode, python3-reportlab, python3-requests, python3-rjsmin, python3-serial, python3-stdnum, python3-tz, python3-urllib3, python3-usb, python3-vobject, python3-werkzeug, python3-xlrd, python3-xlsxwriter, python3-xlwt, python3-zeep, python3:any, adduser, fonts-dejavu-core | fonts-freefont-ttf | fonts-freefont-otf | fonts-noto-core, fonts-inconsolata, fonts-font-awesome, fonts-roboto-unhinted, gsfonts, libjs-underscore, lsb-base, postgresql-client, python3-freezegun, python3-renderpm
...
結果一看之下,發現內容微妙地不一樣。從 .deb
得到的套件多了許多,但理論上 .deb
的套件內容也是從 debian/control
這個檔案生成的,想不通為什麼會不同,花了些時間比對 odoo 的發布日期也看不出個所以然。
直到後來又仔細觀察這個 control
檔,才發現 Depends:
裡面有 ${misc:Depends}
、${python3:Depends}
這兩個看起來像是變數的東西,應該就是差異所在。
既然從 .deb
來的依賴套件比較完整,最終這就是我們上一章 Dockerfile 裡面 apt install
odoo 依賴套件列表的來源。
這邊有一個思考點:既然我們確定要以 .deb
的 Depends
作為依賴套件列表的來源,能不能再把 python3-
的套件部分移動出去,放到 Poetry 去安裝呢?達到我們原本想要的更精確的版本控制還有檢測衝突等功能。
為此,我寫了一個簡單的腳本,去查看這些 python3-
套件的 apt
依賴:
#!/bin/bash
#
# extract_python_deps.sh
# © 2024 Andrew Shen <wildfootw@hoschoc.com>
#
# Distributed under the same license as odooBundle-Codebase.
#
# Check if a .deb file is provided
if [ $# -eq 0 ]; then
echo "Usage: $0 <path_to_deb_file>"
exit 1
fi
DEB_FILE="$1"
# Check if dpkg-deb is available
if ! command -v dpkg-deb &> /dev/null; then
echo "Error: dpkg-deb is not installed. Please install the dpkg package."
exit 1
fi
# Check if apt-rdepends is available
if ! command -v apt-rdepends &> /dev/null; then
echo "Error: apt-rdepends is not installed. Please run: sudo apt-get install apt-rdepends"
exit 1
fi
# Extract the Depends field from the .deb file
DEPENDS=$(dpkg-deb -I "$DEB_FILE" | grep -E '^ Depends:' | sed 's/^ Depends://' | tr ',' '\n' | sed 's/|.*//' | sed 's/(.*)//' | sed 's/^[ \t]*//' | sed 's/[ \t]*$//')
# Extract packages that start with python3-
PYTHON_PACKAGES=$(echo "$DEPENDS" | grep '^python3-')
if [ -z "$PYTHON_PACKAGES" ]; then
echo "No python3-related packages found in $DEB_FILE."
exit 0
fi
echo "Found the following python3-related packages in $DEB_FILE:"
echo "$PYTHON_PACKAGES"
echo ""
# Run apt-rdepends for each package and collect all dependencies
ALL_DEPENDS=()
for pkg in $PYTHON_PACKAGES; do
echo "Processing dependencies for package $pkg..."
DEP_LIST=$(apt-rdepends "$pkg" 2>/dev/null | grep -E '^[a-zA-Z0-9-]+$')
ALL_DEPENDS+=($DEP_LIST)
done
# Remove duplicate package names
UNIQUE_DEPENDS=($(echo "${ALL_DEPENDS[@]}" | tr ' ' '\n' | sort -u))
echo ""
echo "List of all recursive dependencies:"
for dep in "${UNIQUE_DEPENDS[@]}"; do
echo "$dep"
done
執行:
./extract_python_deps.sh odoo_17.0.latest_all.deb
最後觀察輸出的內容,發現它們的依賴除了更多 python3
套件外,還有很多非 python3
的套件。如果用 Poetry 來管理的話,會缺乏這些東西,而且數量龐大,我如果把它們都列出來再使用 apt
安裝,感覺花費的時間就本末倒置了,所以最後我們還是決定使用 apt
來安裝這些套件就好。